home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / language / sozobon2.zoo / ld / p2.c < prev   
C/C++ Source or Header  |  1990-12-13  |  6KB  |  411 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include "ld.h"
  14.  
  15. extern int vflag, symout, bflag;
  16. extern char *oname;
  17.  
  18. int ifd, ofd;
  19.  
  20. pass2()
  21. {
  22.     register struct oinfo *op;
  23.     int i;
  24.  
  25.     ofd = OPENBW(oname);
  26.     if (ofd < 0) {
  27.         fprintf(stderr, "Cant open output %s\n", oname);
  28.         exit(1);
  29.     }
  30.  
  31.     h.magic = OMAGIC;
  32.     h.tsize = textsize;
  33.     h.dsize = datasize;
  34.     h.bsize = bsssize+comsize;
  35.     if (symout)
  36.         h.syms = nsym * sizeof(struct sym);
  37.     else
  38.         h.syms = 0;
  39.     wwrite(ofd, &h, sizeof(h));
  40.  
  41.     relstart();
  42.     for (op=obj; op < &obj[nobj]; op++)
  43.         if (bflag)
  44.             blink(op, 0);
  45.         else
  46.             mlink(op, 0);
  47.     for (op=obj; op < &obj[nobj]; op++)
  48.         if (bflag)
  49.             blink(op, 1);
  50.         else
  51.             mlink(op, 1);
  52.  
  53.     if (symout)
  54.         for (i=0; i<nsym; i++)
  55.             wwrite(ofd, &sym[i].sy, sizeof(struct sym));
  56.  
  57.     relend();
  58. }
  59.  
  60. long
  61. findx(x, symp, relp)
  62. struct sym *symp;
  63. short *relp;
  64. {
  65.     register struct sym *sp;
  66.     register struct sinfo *lp, *lookup();
  67.  
  68.     x >>= 3;
  69.     sp = &symp[x];
  70.     if (sp->mark == 0) {
  71.         lp = lookup(sp->name);
  72.         if (lp == NULL) {
  73.             fprintf(stderr, "Cant find symbol %.8s\n",
  74.                 sp->name);
  75.             exit(1);
  76.         }
  77.         switch (lp->sy.flags & 7) {
  78.         case 1:
  79.             sp->mark = 3;    break;
  80.         case 2:
  81.             sp->mark = 2;    break;
  82.         case 4:
  83.             sp->mark = 1;    break;
  84.         default:
  85.             fprintf(stderr, "Bad sym type\n");
  86.             exit(1);
  87.         }
  88.         sp->value = lp->sy.value;
  89.     }
  90.     *relp = sp->mark;
  91.     return sp->value;
  92. }
  93.  
  94. blink(op, dat)
  95. register struct oinfo *op;
  96. {
  97.     register long n, i;
  98.     register long tdat, rat;
  99.  
  100.     n = dat ? op->oh.dsize : op->oh.tsize;
  101.     if (n == 0)
  102.         return;
  103.  
  104.     if (vflag >1) {
  105.         printf("%c-", dat ? 'D' : 'T');
  106.         onm_pr(op-obj, stdout);
  107.         putchar('\n');
  108.     }
  109.         
  110.     ifd = files[op->fno].fd;
  111.  
  112.     tdat = op->im_td;
  113.     rat = op->im_rel;
  114.     if (dat) {
  115.         tdat += op->oh.tsize;
  116.         rat += op->oh.tsize;
  117.     }
  118.  
  119.     while (n) {
  120.         i = n;
  121.         if (i > LBUFSZ)
  122.             i = LBUFSZ;
  123.         llseek(ifd, rat, 0);
  124.         rread(ifd, rbuf, (int)i);
  125.         if (i<n && rbuf[LBUFCNT-1] == 5) {
  126.             rread(ifd, &rbuf[LBUFCNT], 2);
  127.             i += 2;
  128.         }
  129.         llseek(ifd, tdat, 0);
  130.         rread(ifd, lbuf, (int)i);
  131.  
  132.         link(op, i, op->im_sym, lbuf, rbuf);
  133.         wwrite(ofd, lbuf, (int)i);
  134.         relout(i, rbuf);
  135.  
  136.         tdat += i;
  137.         rat += i;
  138.         n -= i;
  139.     }
  140. }
  141.  
  142. mlink(op, dat)
  143. register struct oinfo *op;
  144. {
  145.     register long n, i;
  146.     register long tdat, rat;
  147.  
  148.     n = dat ? op->oh.dsize : op->oh.tsize;
  149.     if (n == 0)
  150.         return;
  151.  
  152.     if (vflag >1) {
  153.         printf("%c-", dat ? 'D' : 'T');
  154.         onm_pr(op-obj, stdout);
  155.         putchar('\n');
  156.     }
  157.  
  158.     tdat = op->im_td;
  159.     rat = op->im_rel;
  160.     if (dat) {
  161.         tdat += op->oh.tsize;
  162.         rat += op->oh.tsize;
  163.     }
  164.  
  165.     link(op, n, op->im_sym, tdat, rat);
  166.     relout(n, rat);
  167.     wlwrite(ofd, tdat, n);
  168.  
  169.     if (dat) {
  170.         free(op->im_td);
  171.         free(op->im_rel);
  172.     }
  173. }
  174.  
  175. link(hp, size, symp, textp, relp)
  176. struct oinfo *hp;
  177. struct sym *symp;
  178. long size;
  179. register short *textp;
  180. register short *relp;
  181. {
  182.     long num, i, v;
  183.     short x;
  184.     short bufs;
  185.     long bufl;
  186.  
  187.     num = size/sizeof(short);
  188.  
  189.     for (i=0; i<num; i++) {
  190.         x = *relp++;
  191.  
  192.         switch (x) {
  193.         case 7:
  194.         case 0:
  195.             textp++;
  196.             break;
  197.         case 5:
  198.             x = *relp;
  199.             if ((x & 7) == 4) {
  200.                 v = findx(x, symp, relp);
  201.             } else
  202.             switch (x) {
  203.             case 0:
  204.                 goto skip;
  205.                 break;
  206.             case 1:
  207.                 v = hp->dbase;
  208.                 break;
  209.             case 2:
  210.                 v = hp->tbase;
  211.                 break;
  212.             case 3:
  213.                 v = hp->bbase;
  214.                 break;
  215.             default:
  216.                 fprintf(stderr, "Bad reloc\n");
  217.                 exit(1);
  218.             }
  219.  
  220.             *(long *)textp += v;
  221. skip:
  222.             textp += 2;
  223.             relp++;
  224.             i++;
  225.             break;
  226.         default:
  227.             fprintf(stderr, "Bad reloc\n");
  228.             exit(1);
  229.         }
  230.     }
  231. }
  232.  
  233. long reloffs;
  234. int relbeg;
  235.  
  236. relstart()
  237. {
  238.     reloffs = 0;
  239.     relbeg = 1;
  240.     rinit();
  241. }
  242.  
  243. relout(n, relp)
  244. long n;
  245. register short *relp;
  246. {
  247.     short x;
  248.     register long i, cnt;
  249.     long lasti;
  250.  
  251.     lasti = -reloffs;
  252.     cnt = n/sizeof(short);
  253.     for (i=0; i<cnt; i++) {
  254.  
  255.         x = *relp++;
  256.  
  257.         switch (x) {
  258.         case 7:
  259.         case 0:
  260.             break;
  261.         case 5:
  262.             x = *relp;
  263.             switch (x) {
  264.             case 0:
  265.                 goto skip;
  266.                 break;
  267.             case 1:
  268.             case 2:
  269.             case 3:
  270.                 seerel(i-lasti);
  271.                 lasti = i;
  272.                 break;
  273.             default:
  274.                 fprintf(stderr, "Bad reloc\n");
  275.                 exit(1);
  276.             }
  277.  
  278. skip:
  279.             relp++;
  280.             i++;
  281.             break;
  282.         default:
  283.             fprintf(stderr, "?%x? ", x);
  284.             exit(1);
  285.         }
  286.     }
  287.     reloffs = i-lasti;
  288. }
  289.  
  290. seerel(n)
  291. long n;
  292. {
  293.     union {
  294.         long ls;
  295.         char bs[4];
  296.     } lb;
  297.     char c;
  298.     int i;
  299.  
  300.     if (relbeg) {
  301.         relbeg = 0;
  302.         lb.ls = 2*n;
  303.         for (i=0; i<4; i++)
  304.             rputc(lb.bs[i]);
  305.         return;
  306.     }
  307.     n *= 2;
  308.     while (n > 254) {
  309.         rputc(1);
  310.         n -= 254;
  311.     }
  312.     c = n;
  313.     rputc(c);
  314. }
  315.  
  316. relend()
  317. {
  318.     rputc(0);
  319.     rdump();
  320. }
  321.  
  322. #define RBSZ    512
  323.  
  324. struct rbuf {
  325.     struct rbuf *next;
  326.     char buf[RBSZ];
  327. } *rbp, *rblast;
  328. char *rbcur;
  329. int rbleft;
  330.  
  331. rinit()
  332. {
  333.     char *myalloc();
  334.  
  335.     rbp = (struct rbuf *)myalloc((long)sizeof(struct rbuf));
  336.     rblast = rbp;
  337.     rbcur = rbp->buf;
  338.     rbleft = RBSZ;
  339. }
  340.  
  341. rputc(c)
  342. char c;
  343. {
  344.     char *myalloc();
  345.     struct rbuf *new;
  346.  
  347.     if (rbleft == 0) {
  348.         new = (struct rbuf *)myalloc((long)sizeof(struct rbuf));
  349.         rblast->next = new;
  350.         rblast = new;
  351.         rbcur = rblast->buf;
  352.         rbleft = RBSZ;
  353.     }
  354.     *rbcur++ = c;
  355.     rbleft--;
  356. }
  357.  
  358. rdump()
  359. {
  360.     register struct rbuf *rp;
  361.  
  362.     for (rp = rbp; rp != rblast; rp = rp->next)
  363.         wwrite(ofd, rp->buf, RBSZ);
  364.     wwrite(ofd, rblast->buf, RBSZ-rbleft);
  365. }
  366.  
  367. rread(fd, buf, n)
  368. char *buf;
  369. {
  370.     if (read(fd, buf, n) != n) {
  371.         fprintf(stderr, "Read failure\n");
  372.         exit(1);
  373.     }
  374.     return n;
  375. }
  376.  
  377. wwrite(fd, buf, n)
  378. char *buf;
  379. {
  380.     if (write(fd, buf, n) != n) {
  381.         fprintf(stderr, "Write failure\n");
  382.         exit(1);
  383.     }
  384.     return n;
  385. }
  386.  
  387. wlwrite(fd, buf, n)
  388. char *buf;
  389. long n;
  390. {
  391.     long lwrite();
  392.  
  393.     if (lwrite(fd, buf, n) != n) {
  394.         fprintf(stderr, "Write failure\n");
  395.         exit(1);
  396.     }
  397.     return n;
  398. }
  399.  
  400. llseek(fd, ln, how)
  401. long ln;
  402. {
  403.     long lseek(), rv;
  404.  
  405.     rv = lseek(fd, ln, how);
  406.     if (rv < 0) {
  407.         fprintf(stderr, "Lseek error\n");
  408.         exit(1);
  409.     }
  410. }
  411.